package com.kaigejava.rulesengine.engine.core.utils;

import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.*;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Random;

/**
 * @author kaigejava
 */
public class FileUtil {

    private static File file = null;

    private static boolean flag = false;

    private static final Logger logger = LoggerFactory.getLogger(FileUtil.class);

    /**
     * 在文件末尾追加内容
     *
     * @param file    要操作的文件
     * @param content 要追加的内容
     * @return
     */
    public static void appendContentToFile(File file, String content) {
        FileWriter writer = null;
        try {
            // 打开一个写文件器，true表示以追加形式写文件
            writer = new FileWriter(file.getAbsolutePath(), true);
            writer.write(content);
        } catch (IOException e) {
            logger.error("appendContentToFile===========error=", e);
        } finally {
            try {
                if (writer != null) {
                    writer.close();
                }
            } catch (IOException e) {
                logger.error("appendContentToFile===========error=", e);
            }
        }
    }

    /**
     * 根据路径删除指定的目录或文件，无论存在与否
     *
     * @param sPath 要删除的目录或文件
     * @return 删除成功返回 true，否则返回 false。
     */
    public static boolean deleteFolder(String sPath) {
        logger.info("deleteFolder===========sPath：" + sPath);
        flag = false;
        file = new File(sPath);
        /**
         * 判断目录或文件是否存在,不存在返回 false
         */
        if (!file.exists()) {
            logger.info("deleteFolder=========file.exists====flag：" + flag);
            return flag;
        } else {
            /**
             * 为文件时调用删除文件方法
             */
            if (file.isFile()) {
                flag = deleteFile(sPath);
                logger.info("deleteFolder=======deleteFile====flag：" + flag);
                return flag;
            }
            return flag;
        }
    }

    /**
     * 删除单个文件
     *
     * @param sPath 被删除文件的文件名
     * @return 单个文件删除成功返回true，否则返回false
     */
    public static boolean deleteFile(String sPath) {
        flag = false;
        file = new File(sPath);
        /**
         * 路径为文件且不为空则进行删除
         */
        if (file.isFile() && file.exists()) {
            file.delete();
            flag = true;
        }
        return flag;
    }

    /**
     * 流转化成字符串
     *
     * @param is
     * @return String
     * @throws Exception
     */
    public static String inputStream2String(InputStream is) {
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        String ss = "";
        try {
            int i = -1;
            while ((i = is.read()) != -1) {
                baos.write(i);
            }
            ss = baos.toString();
        } catch (Exception e) {
            logger.error("inputStream2String===========error=", e);
        } finally {
            try {
                if (baos != null) {
                    baos.flush();
                    baos.close();
                }
                if (is != null) {
                    is.close();
                }
            } catch (IOException e) {
            }
        }
        return ss;
    }

    /**
     * 流转化成文件
     *
     * @param is
     * @throws Exception
     */
    public static File inputStream2File(InputStream is, String saveFilePath) {
        File file = new File(saveFilePath);
        BufferedInputStream fis = new BufferedInputStream(is);
        FileOutputStream fos = null;
        try {
            fos = new FileOutputStream(file);
            int f;
            while ((f = fis.read()) != -1) {
                fos.write(f);
            }
        } catch (FileNotFoundException e) {
            logger.error("inputStream2FileFileNotFoundException,message:{}", e);
        } catch (IOException e) {
            logger.error("inputStream2FileIOException,message:{}", e);
        } finally {
            try {
                if (fos != null) {
                    fos.flush();
                    fos.close();
                }
                if (fis != null) {
                    fis.close();
                }
                if (is != null) {
                    is.close();
                }
            } catch (IOException e) {
                logger.error("BufferStreamCloseFailed,message:{}", e);
            }
        }
        return file;
    }

    /**
     * 计算文件大小，如果返回为0，表示该文件不存在或者获取过程中发生异常
     *
     * @param file
     * @return
     */
    public static long calculateFileSize(File file) {
        //定义文件输入流，用于获取文件大小
        FileInputStream inStream = null;
        long byteSize = 0;
        try {
            inStream = new FileInputStream(file);
            byteSize = inStream.available();
        } catch (Exception e) {
            logger.error("##calculateFileSize读写文件" + file.getName() + "发生异常", e);
        } finally {
            if (null != inStream) {
                try {
                    inStream.close();
                } catch (IOException e) {
                    logger.error("##calculateFileSize读写文件" + file.getName() + "发生异常", e);
                }
            }
        }
        return byteSize;
    }

    /**
     * 判断文件名 xx.xxx 是否合法
     *
     * @return
     */
    public static boolean isFilenameValid(String fileName) {
        if (fileName == null) {
            return false;
        }
        String role = "[^\\s\\\\/:\\*\\?\\\"<>\\|](\\x20|[^\\s\\\\/:\\*\\?\\\"<>\\|])*[^\\s\\\\/:\\*\\?\\\"<>\\|\\.]$";
        return fileName.matches(role);
    }

    /**
     * 判断文件是否存在
     *
     * @param file
     * @return
     */
    public static boolean exists(File file) {
        if (file == null) {
            return false;
        }
        return file.exists();
    }

    /**
     * 生成文件名：文件名前缀_15位时间戳+(length-15)位随机号
     *
     * @param prefix 文件名前缀
     * @return 例如：vdback_16080409313454865242
     */
    public static String createFilename(String prefix, int length) {
        return prefix + "_" + getSeqByLength(length);
    }

    private static String genTimeStr() {
        SimpleDateFormat sdf = new SimpleDateFormat("yyMMddHHmmssSSS");
        String timeStr = sdf.format(new Date());
        return timeStr;
    }

    /**
     * 生成序列号
     */
    private static String getSeqByLength(int totalLength) {
        String timeStr = genTimeStr();
        int coverPad = totalLength - timeStr.length();
        int random = new Random().nextInt(100000);
        String seq = StringUtils.leftPad(String.valueOf(random), coverPad, "0");
        return timeStr + seq;
    }

    /**
     * inputStream2String
     *
     * @param in
     * @param encoding
     * @return
     */
    public static String inputStream2String(InputStream in, String encoding) {
        StringBuilder out = new StringBuilder();
        InputStreamReader inread;
        try {
            inread = new InputStreamReader(in, encoding);
            char[] b = new char[4096];
            for (int n; (n = inread.read(b)) != -1; ) {
                out.append(new String(b, 0, n));
            }
        } catch (Exception e) {
            logger.error("##inputStream2String error1=", e);
        } finally {
            if (in != null) {
                try {
                    in.close();
                } catch (IOException e) {
                    logger.error("##inputStream2String error2=", e);
                }
            }
        }
        return out.toString();
    }

    /**
     * 读文件
     *
     * @param filename
     * @return
     */
    public static byte[] readPic(String filename) {
        byte[] buffer = null;
        FileInputStream in = null;
        try {
            File file = new File(filename);
            if (file.canRead() && file.isFile()) {
                in = new FileInputStream(file);
                int length = in.available();
                buffer = new byte[length];
            }
        } catch (Exception e) {
            logger.error("ReadPicException,message:{}", e);
        } finally {
            if (in != null) {
                try {
                    in.close();
                } catch (IOException e) {
                    logger.error("StreamCloseException,message:{}", e);
                }
            }
        }

        return buffer;
    }
}
